﻿using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Aeon.Configuration;
using Aeon.Emulator.Dos.VirtualFileSystem;

namespace Aeon.Emulator.Launcher
{
    /// <summary>
    /// Control for editing a drive mounting configuration.
    /// </summary>
    public partial class DiskMounter : UserControl
    {
        #region Public Static Fields
        /// <summary>
        /// The dependency property definition for the ItemsSource property.
        /// </summary>
        public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(MountedDriveCollection), typeof(DiskMounter), new PropertyMetadata(null));
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the DiskMounter class.
        /// </summary>
        public DiskMounter()
        {
            InitializeComponent();
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets or sets the source item collection.
        /// </summary>
        public MountedDriveCollection ItemsSource
        {
            get { return (MountedDriveCollection)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Called when a list view item is activated.
        /// </summary>
        private void OnItemActivated()
        {
            var item = driveList.SelectedItem as MountedDrive;
            if(item != null && propertiesCommand.Command.CanExecute(null))
                propertiesCommand.Command.Execute(null);
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Invoked to determine whether the New command can execute.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void NewCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if(this.ItemsSource != null)
                e.CanExecute = this.ItemsSource.Count < 26;
            else
                e.CanExecute = false;
        }
        /// <summary>
        /// Invoked to determine whether the Delete command can execute.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void DeleteCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if(this.driveList != null)
                e.CanExecute = this.driveList.SelectedItem != null;
            else
                e.CanExecute = false;
        }
        /// <summary>
        /// Invoked to determine whether the Properties command can execute.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void PropertiesCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if(this.driveList != null)
                e.CanExecute = this.driveList.SelectedItem != null;
            else
                e.CanExecute = false;
        }
        /// <summary>
        /// Invoked when the New command is executed.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void NewCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if(this.ItemsSource != null)
            {
                var newDrive = new MountedDrive
                {
                    DriveLetter = (DriveLetter)this.ItemsSource.NextAvailableDriveLetter,
                    DriveType = DriveType.Floppy35,
                    DriveConfiguration = new MappedFolderConfiguration()
                };

                var dialog = new DriveProperties
                {
                    AvailableDriveLetters = this.ItemsSource.AvailableDriveLetters,
                    MountedDrive = newDrive,
                    Owner = Window.GetWindow(this)
                };

                if(dialog.ShowDialog() == true)
                    this.ItemsSource.Add(newDrive);
            }
        }
        /// <summary>
        /// Invoked when the Delete command is executed.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void DeleteCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var collection = this.ItemsSource;
            if(collection != null)
            {
                var selectedItems = this.driveList.SelectedItems.Cast<MountedDrive>().ToList();
                foreach(var item in selectedItems)
                    collection.Remove(item);
            }
        }
        /// <summary>
        /// Invoked when the Properties command is executed.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void PropertiesCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if(this.ItemsSource != null)
            {
                var drive = this.driveList.SelectedItem as MountedDrive;
                if(drive != null)
                {
                    var dialog = new DriveProperties
                    {
                        AvailableDriveLetters = this.ItemsSource.AvailableDriveLetters.Union(new[] { drive.DriveLetter }),
                        MountedDrive = drive.Clone(),
                        Owner = Window.GetWindow(this)
                    };

                    if(dialog.ShowDialog() == true)
                    {
                        this.ItemsSource.Remove(drive);
                        this.ItemsSource.Add(dialog.MountedDrive);
                    }
                }
            }
        }
        /// <summary>
        /// Invoked when the drive list is double-clicked.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void DriveList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            OnItemActivated();
        }
        /// <summary>
        /// Invoked when a key is pressed on the drive list.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void DriveList_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.Key == Key.Enter)
                OnItemActivated();
        }
        #endregion
    }
}
